package org.third.common.datasource;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;

import org.hibernate.MultiTenancyStrategy;
import org.hibernate.cfg.Environment;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.third.common.domain.Deployment;

/**
 * Created by Huailong Tang(Jason) on 2017/10/16.
 */
@Configuration
@EnableConfigurationProperties({JpaProperties.class})
@EnableTransactionManagement(proxyTargetClass = true)
@EnableJpaRepositories(basePackages = {"suiteinstaller.v1_1.domain"},transactionManagerRef = "transactionManager")
public class InstallerJpaConfiguration {

  @Autowired
  private DataSourceProperties dataSourceProperties;

  @Autowired
  private JpaProperties jpaProperties;

  @Bean
  public MultiTenantConnectionProvider multiTenantConnectionProvider(){
    return new DataSourceBasedMultiTenantConnectionProviderImpl();
  }

  @Bean
  public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {
    return  new CurrentTenantIdentifierResolverImpl();
  }

  @Bean(name = "installerDataSource")
  public Map<String,DataSource> installerDatasource() {
    Map<String,DataSource> datasources = new HashMap<>();
    return datasources;
  }

  @Primary
  @Bean
  @PersistenceContext
  public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(MultiTenantConnectionProvider multiTenantConnectionProvider,
      CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {

    Map<String,Object> hibernateProps = new LinkedHashMap<>();
    hibernateProps.putAll(this.jpaProperties.getProperties());
    hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
    hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER,multiTenantConnectionProvider);
    hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER,currentTenantIdentifierResolver);

    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    //use Deployment's package as basePackage
    em.setPackagesToScan(new String[]{Deployment.class.getPackage().getName()});
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    em.setJpaPropertyMap(hibernateProps);

    return em;
  }

  @Bean
  public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean){
    return entityManagerFactoryBean.getObject();
  }

  @Bean(name = "transactionManager")
  public PlatformTransactionManager txManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager tx = new JpaTransactionManager();
    tx.setEntityManagerFactory(entityManagerFactory);
    return tx;
  }



}
